﻿/************************************************************************************
 *      Copyright (C) 2017 dawenyang,All Rights Reserved
 *      File:
 *                ServiceHelper.cs
 *      Description:
 *            ServiceHelper
 *      Author:
 *                yxw
 *                
 *                
 *      Finish DateTime:
 *                2017/12/4 17:10:31
 *      History:
 ***********************************************************************************/

using System;
using System.Threading;
using Castle.DynamicProxy;
using Core.Log.Model;
using FrameWork.Util.Extension;
using FrameWork.Util.Http;
using MyDb.DoMain.Entity.DbEntity;
using MyDb.DoMain.Interface;
using ProxyGenerator = Castle.DynamicProxy.ProxyGenerator;

namespace FrameWork.Web
{
    /// <summary>
    /// 创建service
    /// </summary>
    public class ServiceHelper
    {
        /// <summary>
        /// 暂时使用引用服务方式，可以改造成注入，或使用WCF服务方式
        /// </summary>
        public static ServiceFactory serviceFactory = new RefServiceFactory();

        /// <summary>
        /// 创建服务根据BLL接口
        /// </summary>
        public static T CreateService<T>() where T : class
        {
            var service = serviceFactory.CreateService<T>();

            //拦截，可以写日志....
            var generator = new ProxyGenerator();
            var dynamicProxy = generator.CreateInterfaceProxyWithTargetInterface<T>(
                service, new InvokeInterceptor());

            return dynamicProxy;
        }

        /// <summary>
        /// 只用来创建没有拦截器的logservice
        /// </summary>
        /// <returns></returns>
        public static ILogService CreateLogService()
        {
            var service = serviceFactory.CreateService<ILogService>();

            //拦截，可以写日志....
            var generator = new ProxyGenerator();
            var dynamicProxy = generator.CreateInterfaceProxyWithTargetInterface(service);

            return dynamicProxy;
        }

    }

    /// <summary>
    /// 拦截器
    /// </summary>
    internal class InvokeInterceptor : IInterceptor
    {
        public InvokeInterceptor()
        {
        }
        /// <summary>
        /// 拦截方法
        /// </summary>
        /// <param name="invocation">拦截器</param>
        public void Intercept(IInvocation invocation)
        {
            try
            {
                invocation.Proceed();
            }
            catch (Exception exception)
            {
                var ip = IpHelp.GetClientIp();
                var message = new
                {
                    exception = exception.Message,
                    exceptionContext = new
                    {
                        method = invocation.Method.ToString(),
                        arguments = invocation.Arguments,
                        returnValue = invocation.ReturnValue
                    },
                    ip
                };
                var str = message.ToJson();
                LogHelper.Start(exception, str, ip);
                throw;
            }
        }
    }

    /// <summary>
    /// 记录日志
    /// </summary>
    internal class LogHelper
    {
        private static readonly ILogService LogService = ServiceHelper.CreateLogService();

        /// <summary>
        /// 记录错误日志到数据库
        /// </summary>
        private static void AddEntity(Exception exception, string json, string ip)
        {
            var entity = new Log4Net
            {
                Date = DateTime.Now,
                Thread = Convert.ToString(Thread.CurrentThread.ManagedThreadId),
                Level = "ERROR",
                Logger = "mydbexception",
                Host = ip,
                Exception = exception.ToString(),
                Message = json
            };
            LogService.AddLog4Net(entity);
        }

        /// <summary>
        /// 启动线程
        /// </summary>
        public static void Start(Exception exception, string json,string ip)
        {
            Action act = () => AddEntity(exception, json, ip);
            act.BeginInvoke(null, null);
        }

        /// <summary>
        /// 添加操作日志
        /// </summary>
        /// <param name="auditLog">操作日志实体</param>
        private static void AddAuditLog(AuditLog auditLog)
        {
            
        }
    }
}
